﻿using System;
using System.ApplicationModel;
using System.ApplicationModel.Composition;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Text;
using Anagramme.Contracts;
using Anagramme.Services;
using Anagramme.Views;
using System.Diagnostics;
using System.Runtime.CompilerServices;

namespace Anagramme.ViewModels
{
    /// <summary>
    /// Classe de base pour les ViewModels
    /// </summary>
    public abstract class ViewModelBase : ObservableObject
    {
        #region Static Fields
        private static Player _player;
        #endregion

        #region Fields
        private int _waitingActions = 0;
        private bool _isBusy;
        #endregion

        #region Properties
        /// <summary>
        /// Obtient une valeur indiquant si le ViewModel est en attente de la fin d'une opération asynchrone
        /// </summary>
        public bool IsBusy
        {
            get { return this._isBusy; }
            private set
            {
                RaisePropertyChanging();
                this._isBusy = value;
                RaisePropertyChanged();
            }
        }

        /// <summary>
        /// Obtient les informations sur le joueur courant
        /// </summary>
        public Player Player
        {
            get { return _player; }
            set
            {
                if (!object.ReferenceEquals(_player, value))
                {
                    RaisePropertyChanging();
                    _player = value;
                    RaisePropertyChanged();
                }
            }
        }
        #endregion

        #region Methods
        /// <summary>
        /// Indique la fin d'une opération asynchrone
        /// </summary>
        protected void BeginWaitingAction()
        {
            this._waitingActions++;
            this.IsBusy = this._waitingActions != 0;
        }

        /// <summary>
        /// Indique le début d'une opération asynchrone
        /// </summary>
        protected void EndWaitingAction()
        {
            if (this._waitingActions > 0)
            {
                this._waitingActions--;
                this.IsBusy = this._waitingActions != 0;
            }
        }

        /// <summary>
        /// Trace a property assignation
        /// </summary>
        /// <param name="value">Assigned value</param>
        /// <param name="propertyName">Concerned property</param>
        protected void TraceAssign(object value, [CallerMemberName] string propertyName = "")
        {
            ApplicationServices.Trace.TraceAssign(value, propertyName);
        }
        #endregion
    }

    /// <summary>
    /// Classe de base pour les ViewModels
    /// </summary>
    /// <typeparam name="TModel">Model associé</typeparam>
    public abstract class ViewModelBase<TModel> : ViewModelBase
        where TModel : class
    {
        #region Fields
        private WeakReference _model;
        #endregion

        #region Properties
        /// <summary>
        /// Obtient le Model associé à la classe
        /// </summary>
        protected TModel Model
        {
            get
            {
                if (object.ReferenceEquals(this._model, null))
                {
                    this._model = new WeakReference(ApplicationServices.Container.GetExportedValue<TModel>());
                }

                return this._model.IsAlive ? this._model.Target as TModel : null;
            }
        }
        #endregion
    }
}
